/*
 * @Author: pardon110
 * @Date: 2024-03-26 16:59:44
 * @LastEditors: pardon110@qq.com
 * @LastEditTime: 2024-03-27 15:42:31
 * @FilePath: \days7\orm\reflect-schema\session\raw.go
 * @Description:
 */
package session

import (
	"database/sql"
	"strings"

	"days7.test/orm/clause"
	"days7.test/orm/log"
	"days7.test/orm/reflect-schema/dialect"
	"days7.test/orm/reflect-schema/schema"
)

// Session keep a pointer to sql.DB
type Session struct {
	db       *sql.DB
	dialect  dialect.Dialect
	tx       *sql.Tx
	refTable *schema.Schema // 持有当前表结构对象引用
	clause   clause.Clause  // 具备子句构建能力
	sql      strings.Builder
	sqlVars  []interface{}
}

func New(db *sql.DB, dialect dialect.Dialect) *Session {
	return &Session{db: db, dialect: dialect} // 其余成员变量延迟初始化
}

// Clear initializes the state of a session
func (s *Session) Clear() {
	s.sql.Reset()
	s.sqlVars = nil
	s.clause = clause.Clause{}
}

type CommonDB interface {
	Query(query string, args ...interface{}) (*sql.Rows, error)
	QueryRow(query string, args ...interface{}) *sql.Row
	Exec(query string, args ...interface{}) (sql.Result, error)
}

var _ CommonDB = (*sql.DB)(nil)
var _ CommonDB = (*sql.Tx)(nil)

// DB  getter sql.DB pointer
func (s *Session) DB() CommonDB {
	// 隐式调用事务兼容基础接口的使用
	if s.tx != nil {
		return s.tx
	}
	return s.db
}

// Exec raw sql with sqlVars
func (s *Session) Exec() (result sql.Result, err error) {
	defer s.Clear()
	log.Info(s.sql.String(), s.sqlVars)
	if result, err = s.DB().Exec(s.sql.String(), s.sqlVars...); err != nil {
		log.Error(err)
	}
	return
}

// QueryRow get a record from db
func (s *Session) QueryRow() *sql.Row {
	defer s.Clear()
	log.Info(s.sql.String(), s.sqlVars)
	return s.DB().QueryRow(s.sql.String(), s.sqlVars...)
}

func (s *Session) QueryRows() (rows *sql.Rows, err error) {
	defer s.Clear()
	log.Info(s.sql.String(), s.sqlVars)
	if rows, err = s.DB().Query(s.sql.String(), s.sqlVars...); err != nil {
		log.Error(err)
	}
	return
}

func (s *Session) Raw(sql string, values ...interface{}) *Session {
	s.sql.WriteString(sql)
	s.sql.WriteString(" ")
	s.sqlVars = append(s.sqlVars, values...)

	// 支持链式调用
	return s
}
